home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / RTF / textrect.C < prev    next >
C/C++ Source or Header  |  1994-08-01  |  6KB  |  286 lines

  1. /* $Header: /usr/people/pcd/Src/RTF/RCS/textrect.C,v 1.1 92/11/23 12:58:56 pcd Exp Locker: pcd $
  2.  */
  3.  
  4. #include "textrect.h"
  5.  
  6.  
  7. #include <stdlib.h>
  8. #include <assert.h>
  9. extern int debug_format = 0;
  10. #include "debug.h"
  11.  
  12. TextRect::TextRect()
  13. {
  14.   lines = 0;
  15. }
  16.  
  17. TextPosition
  18. TextRect::format(const TextFlow* flow, TextPosition first, TextPosition last,
  19.          const BRect& available)
  20. {
  21.   if(flow == 0) return first; //@# need this?
  22.   bounds_ = available;
  23.   LRBox*    l = lines;
  24.   Extent    used;
  25.  
  26.   while(first < last){
  27.     Extent margins;
  28.     TextPosition local=first;
  29.     flow->leaf(first, local)->line_shape(local, margins);//@# optimize this
  30.  
  31.     if(margins.current_x() + margins.right() < bounds().width()
  32.        && margins.top() < bounds().height()){
  33.       Extent avail(bounds().left(),
  34.            bounds().left() + margins.left(),
  35.            bounds().right() - margins.right(),
  36.            bounds().top() + margins.top(),
  37.            bounds().bottom());
  38.       l = new LRBox(l);
  39.       first =  l->format(flow, first, last, avail, used,
  40.              margins.x0); //justification
  41.       if(used.bad()){
  42.     l = l->destroy();
  43.     break;
  44.       }
  45.     }else
  46.       break;
  47.  
  48.     bounds_.inc_top(margins.top() + used.height());
  49. #if SPACE_AFTER /*@@BUG*/
  50.     flow->line_shape(first, margins);
  51. #endif
  52.     bounds_.inc_top(margins.bottom());
  53.   }
  54.  
  55.   lines = l;
  56.   return first;
  57. }
  58.  
  59. void
  60. TextRect::render(const BRect& bounds)
  61. {
  62.   LRBox* l = lines;
  63.   while(l && l->top() > bounds.bottom())
  64.     l = l->prev();
  65.  
  66.   while(l && l->bottom() > bounds.top()){
  67.     l->render(bounds);
  68.     l = l->prev();
  69.   }
  70. }
  71.  
  72.  
  73. TextPosition
  74. TextRect::position(Coord x, Coord y)
  75. {
  76.   LRBox* l;
  77.   for(l = lines; l; l = l->prev())
  78.     if(y > l->top())
  79.       return l->position(x);
  80.     else if(l->prev() == 0)
  81.       return l->position(0);
  82. }
  83.  
  84. Coord
  85. TextRect::locate(TextPosition here, Coord *top, Coord* bottom) const
  86. {
  87.   LRBox* l;
  88.   for(l = lines; l; l = l->prev())
  89.     if(here >= l->first()){
  90.       if(top) *top = l->top();
  91.       if(bottom) *bottom = l->bottom();
  92.       return l->locate(here);
  93.     }
  94.  
  95.   if(top) *top = 0;
  96.   if(bottom) *bottom = 0;
  97.   return -1;
  98. }
  99.  
  100. /****** Box ******/
  101.  
  102. Box::Box(Box* prev)
  103. {
  104.   prev_ = prev;
  105.   formnode = 0;
  106.   bytes = 0;
  107.   f = first_ = -1;
  108. }
  109.  
  110. TextPosition
  111. Box::format(const TextFlow* flow, TextPosition first, TextPosition last,
  112.         Extent avail, Extent& used, int word_wrap)
  113. {
  114.   f = first_ = first;
  115.   formnode = flow->leaf(first, first_);
  116.  
  117.   if(formnode){
  118.     Qty q = last - first;
  119.     if(q > formnode->bytes() - first_)
  120.       q = formnode->bytes() - first_;
  121.     Debug(format, ("formatting: [%.*s]\n", q, formnode->data()+first_));
  122.     if(bytes = formnode->character_shape(first_, q,
  123.                      avail, used, word_wrap)){
  124.       Debug(format, ("%d bytes formatted.\n", bytes));
  125.       return first + bytes;
  126.     }
  127.   }
  128.   Debug(format, ("won't fit at %d.\n", avail.current_x()));
  129.   used.make_bad();
  130.   return first;
  131. }
  132.  
  133. void
  134. Box::y(Coord yy) //@# should be an LRBox member
  135. {
  136.   Box* bx;
  137.   for(bx = this; bx; bx = bx->prev())
  138.     bx->location.y = yy;
  139. }
  140.  
  141.  
  142. void
  143. Box::move(Coord dx) //@# should be an LRBox member
  144. {
  145.   Box* bx;
  146.   for(bx = this; bx; bx = bx->prev())
  147.     bx->location.x += dx;
  148. }
  149.  
  150.  
  151. void
  152. Box::render(const BRect&)
  153. {
  154.   if(formnode && bytes)
  155.     formnode->render(first_, bytes, location);
  156. }
  157.  
  158. TextPosition
  159. Box::position(const Extent& avail)
  160. {
  161.   Extent used;
  162.   return first() + formnode->character_shape(first_, bytes,
  163.                          avail, used, 0);
  164. }
  165.  
  166. Coord
  167. Box::locate(TextPosition here, Coord top, Coord bottom) const
  168. {
  169.   here -= first();
  170.   assert(here<=bytes);
  171.  
  172.   if(here>0){
  173.     Extent avail(location.x, location.x, location.x+width, top, bottom);
  174.     
  175.     Extent used;
  176.     formnode->character_shape(first_, here,
  177.                   avail, used, 0);
  178.     return location.x + used.width();
  179.   }else
  180.     return location.x;
  181. }
  182.  
  183.  
  184. LRBox::LRBox(LRBox* prev)
  185. {
  186.   prev_ = prev;
  187.   runs = 0;
  188.   f = -1;
  189. }
  190.  
  191. TextPosition
  192. LRBox::position(Coord x)
  193. {
  194.   Box* s;
  195.   Extent avail(0, 0, x, top(), bottom());
  196.  
  197.   for(s = runs; s; s = s->prev())
  198.     if(x > s->left()){
  199.       avail.current_x(s->left());
  200.       return s->position(avail);
  201.     }
  202.     else if(s->prev() == 0){
  203.       return s->first();
  204.     }
  205. }
  206.  
  207. Coord
  208. LRBox::locate(TextPosition here) const
  209. {
  210.   Box* s;
  211.  
  212.   for(s = runs; s; s = s->prev())
  213.     if(here >= s->first()){
  214.       return s->locate(here, top(), bottom());
  215.     }
  216.  
  217.   return 0;
  218. }
  219.  
  220. TextPosition
  221. LRBox::format(const TextFlow* flow, TextPosition first, TextPosition last,
  222.           Extent avail, Extent& total, int just)
  223. {
  224.   Box* b = 0;
  225.   Extent used;
  226.   int word_wrap = 0;
  227.   Coord gap = 0;
  228.   total.y0 = total.y1 = 0;
  229.  
  230.   delete runs;
  231.  
  232.   f = first;
  233.  
  234.   while(first < last){
  235.     b = new Box(b);
  236.     first = b->format(flow, first, last, avail, used, 1);
  237.  
  238.     if(word_wrap == 0 && used.bad())
  239.       first = b->format(flow, first, last, avail, used, 0);
  240.  
  241.     if(used.bad()){
  242.       b = b->destroy();
  243.       if(b == 0)
  244.     total.make_bad();
  245.       break;
  246.     }
  247.     if(used.x2>0) gap = used.x2;
  248.     word_wrap = 1;
  249.     total.max_ascent(used.ascent());
  250.     total.max_descent(used.descent());
  251.     b->x(avail.current_x(), used.width());
  252.     avail.move(used.width());
  253.   }
  254.   runs = b;
  255.   y0_ = avail.ascent();
  256.   ascent = total.ascent();
  257.   descent = total.descent();
  258.  
  259.   /* justify boxes */
  260.   if(b){
  261.     b->y(avail.ascent() + total.ascent());
  262.     if(just == 1)
  263.       b->move(gap); //right just
  264.     else if(just == 2)
  265.       b->move(gap/2); //center just
  266.   }
  267.   
  268.   return first;
  269. }
  270.  
  271.  
  272. void
  273. LRBox::render(const BRect& bounds)
  274. {
  275.   Box* r = runs;
  276.   while(r && r->left() > bounds.right())
  277.     r = r->prev();
  278.  
  279.   while(r && r->right() > bounds.left()){
  280.     r->render(bounds);
  281.     r = r->prev();
  282.   }
  283. }
  284.  
  285.  
  286.